package net.peelmeagrape.hibernate;

import net.peelmeagrape.hibernate.xmlgen.*;
import net.peelmeagrape.hibernate.sql.SqlInsert;
import net.peelmeagrape.hibernate.sql.SqlDelete;
import net.peelmeagrape.hibernate.sql.SqlUpdate;
import net.peelmeagrape.hibernate.sql.Loader;

import static java.lang.annotation.ElementType.TYPE;
import java.lang.annotation.Retention;
import static java.lang.annotation.RetentionPolicy.RUNTIME;
import java.lang.annotation.Target;

/**
 * Subclass using table-per-subclass mapping strategy.
 */
@Target({TYPE}) @Retention(RUNTIME)
@XmlElement(name="union-subclass")
@AddClassNameAsAttribute(name="name")
public @interface H8UnionSubclass
{
    Meta[] meta() default {};

    @XmlAttribute("extends")
    @DefaultFromSuperclass
            Class[] superclass() default {};

    /**
     * @deprecated Unsure how this would work as an annotation.
     */
    @XmlAttribute("entity-name") String entityName() default "";

    /**
     * Specifies an interface to use for lazy initializing proxies.
     * You may specify the class itself.
     * This enables lazy initialization of persistent instances of the class.
     * Hibernate will initially return CGLIB proxies which implement the named
     * interface. The actual persistent object will be loaded when a method of
     * the proxy is invoked. See "Proxies for Lazy Initialization" below.
     * todo: make this link.
     */
    @XmlAttribute Class[] proxy() default {};

    /**
    * (optional - defaults to the unqualified class name): The name of its database table.
    */

    @XmlAttribute String table() default "";

    /**
    * Override the schema name specified by the root &lt;hibernate-mapping&gt; element.
    */
    @XmlAttribute String schema() default "";

    /**
    * Override the catalog name specified by the root &lt;hibernate-mapping&gt; element.
    */
    @XmlAttribute String catalog() default "";

    /**
    * (optional): Maps an immutable and read-only entity to a database subselect.
    * Useful if you want to have a view instead of a base table, but don't.
    * <br/>
    * There is no difference between a view and a base table for a Hibernate
    * mapping, as expected this is transparent at the database level (note that
    * some DBMS don't support views properly, especially with updates).
    * Sometimes you want to use a view, but can't create one in the database
    * (ie. with a legacy schema). In this case, you can map an immutable and
    * read-only entity to a given SQL subselect expression:<br/>
    */
    @XmlAttribute String subselect() default "";

    /**
     * Specifies that UPDATE SQL should be generated at runtime and contain only those columns whose values have changed.
     * Note that the dynamic-update and dynamic-insert  settings are not inherited by
     * subclasses and so may also be specified on the &lt;subclass> or &lt;joined-subclass>
     * elements. These settings may increase performance in some cases, but might actually
     * decrease performance in others. Use judiciously.
     */
    @XmlAttribute("dynamic-update") boolean dynamicUpdate() default false;

    /**
     * Specifies that INSERT SQL should be generated at runtime and contain only the columns whose values are not null.
     * Note that the dynamic-update and dynamic-insert  settings are not inherited by
     * subclasses and so may also be specified on the &lt;subclass> or &lt;joined-subclass>
     * elements. These settings may increase performance in some cases, but might actually
     * decrease performance in others. Use judiciously.
     */
    @XmlAttribute("dynamic-insert") boolean dynamicInsert() default false;

    /**
     * Specifies that Hibernate should never perform an SQL UPDATE unless it is certain
     * that an object is actually modified. In certain cases (actually, only when a transient
     * object has been associated with a new session using update()), this means that Hibernate
     * will perform an extra SQL SELECT to determine if an UPDATE is actually required.
     */
    @XmlAttribute("select-before-update") boolean selectBeforeUpdate() default false;

    /**
     * Lazy fetching may be completely disabled by setting lazy=false.
     */
    @XmlAttribute boolean lazy() default true;

    /**
     * Used to mark abstract superclasses in <union-subclass> hierarchies.
     * todo: superclass/subclass mapping
     */
    @XmlAttribute("abstract") boolean isabstract() default false;

    /**
     * Specifies a custom ClassPersister.
     * Lets you customize the persistence strategy used for the class.
     * You may, for example, specify your own subclass of
     * {@link org.hibernate.persister.entity.BasicEntityPersister}
     * or you might even provide a completely new implementation of the
     * interface {@link org.hibernate.persister.entity.EntityPersister} that implements
     * persistence via, for example, stored procedure calls, serialization to
     * flat files or LDAP. See
     * <code>org.hibernate.test.legacy.CustomPersister</code> for a simple example
     * (of "persistence" to a Hashtable).
     */
    @XmlAttribute Class<? extends org.hibernate.persister.entity.EntityPersister>[] persister() default {};

    @XmlAttribute String check() default "";

    /**
     * specify a "batch size" for fetching instances of this class by identifier.
     */
    @XmlAttribute("batch-size") int batchSize() default 1;

    @XmlAttribute String node() default "";

    Synchronize[] synchronize() default {};
    Comment[] comment() default {};

    UnionSubclass[] subs() default {};

    Loader[] loader() default {};
    SqlInsert[] sqlInsert() default {};
    SqlUpdate[] sqlUpdate() default {};
    SqlDelete[] sqlDelete() default {};
}
